package cn.yunyichina.provider.bed.listener;

import cn.yunyichina.provider.bed.utils.MedicalCardUtil;
import cn.yunyichina.provider.framework.common.PKGenerator;
import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.dubbo.service.HisifaceService;
import cn.yunyichina.provider.framework.dubbo.service.MessageService;
import cn.yunyichina.provider.framework.dubbo.service.PayService;
import cn.yunyichina.provider.framework.exception.CallException;
import cn.yunyichina.provider.iface.entity.base.OrderExceptionVo;
import cn.yunyichina.provider.iface.entity.base.OrderExtVo;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.iface.entity.hisiface.bed.PayOutSettlementVo;
import cn.yunyichina.provider.iface.entity.hisiface.bed.PayOutSettlementVoResponse;
import cn.yunyichina.provider.iface.entity.hisiface.bed.PayDepositVo;
import cn.yunyichina.provider.iface.entity.hisiface.bed.PayDepositVoResponse;
import cn.yunyichina.provider.iface.entity.pay.PaymentJournalVo;
import cn.yunyichina.utils.commons.DateUtils;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.listener.MessageListener;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DepositAliPayMessageListener implements MessageListener<Integer, String> {

    private Logger logger = LoggerFactory.getLogger(DepositAliPayMessageListener.class);

    private final static String TRADE_IS_SUCCESS = "TRADE_SUCCESS";

    public void onMessage(ConsumerRecord<Integer, String> integerStringConsumerRecord) {
        logger.info("DepositAliPayMessageListener onMessage start.");

        String jsonString = integerStringConsumerRecord.value();
        logger.info("DepositAliPayMessageListener.onMessage.jsonString -> {}", jsonString);

        OrderExtVo updateOrderExtVo = new OrderExtVo();

        try {
            JSONObject jsonObject = JSON.parseObject(jsonString);
            String appId = (String) jsonObject.get("app_id");//应用ID
            String orderNo = (String) jsonObject.get("out_trade_no");//商户订单号
            String payStatus = (String) jsonObject.get("trade_status");//交易状态
            String paymentDealId = (String) jsonObject.get("trade_no");//第三方支付公司交易流水号
            String payMode = "22";

            if(jsonObject.get("passback_params") != null ){
                JSONObject passbackParams = JSON.parseObject(jsonObject.getString("passback_params"));
                if(passbackParams.containsKey("pay_mode")){
                    payMode = passbackParams.getString("pay_mode");
                }
            }

            //查询订单
            Map<String, String> updateDataMap = new HashMap<String, String>();
            updateDataMap.put("order_no", orderNo);
            logger.info("【押金补缴支付监听-查询订单信息】, yyt.base.order.by.order.no.out.get request=" + JSON.toJSONString(updateDataMap));
            Response ordUpdateResponse = BaseService.callUnderlineFromInternal("yyt.base.order.by.order.no.out.get",
                    JsonUtils.toJsonString(updateDataMap));
            logger.info("【押金补缴支付监听-查询订单信息】, yyt.base.order.by.order.no.out.get response=" + JSONObject.toJSONString(ordUpdateResponse));
            if (!"0".equals(ordUpdateResponse.getResultCode())) {
                throw new CallException("14010","not found order by order_no=" + orderNo);
            }
            updateOrderExtVo = JsonUtils.parseObject(ordUpdateResponse.getResult(), OrderExtVo.class);

            if(TRADE_IS_SUCCESS.equalsIgnoreCase(payStatus)){
                logger.info("onMessage, 支付成功，start");//支付成功
                updateOrderExtVo.setPayStatusPayed();//支付成功
            }else{
                updateOrderExtVo.setPayStatusFail();//支付失败
            }
            updateOrderExtVo.setPayAppId(appId);
            updateOrderExtVo.setPayMode(Short.parseShort(payMode));
            updateOrderExtVo.setPaymentDealId(paymentDealId);
            updateOrderExtVo.setUpdateTime(DateUtils.dateToString(new Date()));
            updateOrderExtVo.setPayTime(DateUtils.dateToString(new Date()));
            logger.info("DepositAliPayMessageListener, updateOrderExtVo=" + JSONObject.toJSONString(updateOrderExtVo));
            //保存订单信息
            BaseService.callUnderlineFromInternal("yyt.base.order.update", JsonUtils.toJsonString(updateOrderExtVo));

            //支付成功，向HIS写单
            if(TRADE_IS_SUCCESS.equalsIgnoreCase(payStatus)){
                //查询订单
                Map<String, String> dataMap = new HashMap<String, String>();
                dataMap.put("order_no", orderNo);
                logger.info("【押金补缴支付监听-查询订单信息】, yyt.base.order.by.order.no.out.get request=" + JSON.toJSONString(dataMap));
                Response ordResponse = BaseService.callUnderlineFromInternal("yyt.base.order.by.order.no.out.get",
                        JsonUtils.toJsonString(dataMap));
                logger.info("【押金补缴支付监听-查询订单信息】, yyt.base.order.by.order.no.out.get response=" + JSONObject.toJSONString(ordResponse));
                if (!"0".equals(ordResponse.getResultCode())) {
                    throw new CallException("14010","not found order by order_no=" + orderNo);
                }
                OrderExtVo orderExtVo = JsonUtils.parseObject(ordResponse.getResult(), OrderExtVo.class);

                if(orderExtVo.getOrderType() == OrderExtVo.ORDER_TYPE_OUT_HOSPITAL_SETTLEMENT){
                    //出院结算
                    paySettlement(orderExtVo,appId);
                }else {
                    PayDepositVo payDepositVo = new PayDepositVo();
                    JSONObject extraParamsMap = JsonUtils.parseObject(orderExtVo.getExtraParams());
                    String patientId = (String) extraParamsMap.get("patient_id");
                    String admissionNo = (String) extraParamsMap.get("admission_no");
                    String inTime = (String) extraParamsMap.get("in_time");
                    //拼接HIS住院押金补缴支付接口入参
                    payDepositVo.setPatientId(patientId);
                    payDepositVo.setAdmissionNo(admissionNo);
                    payDepositVo.setInTime(inTime);
                    payDepositVo.setYytOrdNum(orderExtVo.getOrderNo());
                    payDepositVo.setAgtOrdNum(orderExtVo.getPaymentDealId());
                    payDepositVo.setAgtCode(appId);
                    payDepositVo.setPayMode("5");//支付宝服务窗支付（含医保）
                    payDepositVo.setPayAmount(orderExtVo.getPayAmount().toString());
                    payDepositVo.setPayTime(orderExtVo.getPayTime());
                    payDepositVo.setHospitalCode(orderExtVo.getOrgCode());
                    Map<String,String> mapExtraParam = new HashMap<>();
                    mapExtraParam.put("pat_card_type",String.valueOf(orderExtVo.getMedicalCardType()));
                    mapExtraParam.put("pat_card_no",orderExtVo.getMedicalCardNo());
                    payDepositVo.setExtendParams(JsonUtils.toJsonString(mapExtraParam));
                    logger.info("【押金补缴支付监听-HIS写单】 request=" + JSONObject.toJSONString(payDepositVo));
                    ResCommon<PayDepositVoResponse> payDepositVoResponse = HisifaceService.getHisifaceClient().payDeposit(payDepositVo);
                    PayDepositVoResponse payDeposit = JsonUtils.parseObject(payDepositVoResponse.getResult(),
                            PayDepositVoResponse.class);
                    logger.info("【押金补缴支付监听-HIS写单】 response=" + JSONObject.toJSONString(payDeposit));
                    if ("0".equals(payDepositVoResponse.getResultCode())) {
                        orderExtVo.setHisOrderNo(payDeposit.getHisOrdNum());
                        orderExtVo.setHisMessage(payDepositVoResponse.getResultMessage());
                        orderExtVo.setReceiptNum(payDeposit.getReceiptNum());
                        orderExtVo.setOrderStatusSuccess();
                        orderExtVo.setUpdateTime(DateUtils.dateToString(new Date()));
                        logger.info("DepositAliPayMessageListener, his_updateOrderExtVo=" + JSONObject.toJSONString(orderExtVo));
                        //保存订单信息
                        BaseService.callUnderlineFromInternal("yyt.base.order.update", JsonUtils.toJsonString(orderExtVo));

                        //更新支付流水
                        PaymentJournalVo tmp = new PaymentJournalVo();
                        tmp.setOrderNo(orderExtVo.getOrderNo());
                        tmp.setPayStatus((short) 1);
                        logger.info("【押金补缴支付监听-更新支付流水】addPaymentJournal, paymentJournal=" + JSON.toJSONString(tmp));
                        Response findPaymentJournalResponse = PayService.callUnderlineFromInternal("yyt.pay.payment.journal.find",
                                JsonUtils.toJsonString(tmp));
                        logger.info("【押金补缴支付监听-更新支付流水】addPaymentJournal, findPaymentJournalResponse=" + JSON.toJSONString(findPaymentJournalResponse));
                        if ("0".equals(findPaymentJournalResponse.getResultCode())) {
                            List<PaymentJournalVo> pjs = JsonUtils.parseArray(findPaymentJournalResponse.getResult(),
                                    PaymentJournalVo.class);
                            PaymentJournalVo psv = pjs.get(0);
                            psv.setHisOrderNo(payDeposit.getHisOrdNum());
                            logger.info("【押金补缴支付监听-更新支付流水】修改支付流水请求参数->" + JSON.toJSONString(psv));
                            PayService.callUnderlineFromInternal("yyt.pay.payment.journal.update", JsonUtils.toJsonString(psv));
                        }

                        //文本消息推送
                        try {
                            Map<String, String> msgMap = new HashMap<String, String>();
                            String patientMsg = "";
                            if (StringUtils.isNotBlank(orderExtVo.getMedicalCardNo())) {
                                patientMsg = MedicalCardUtil.desName(orderExtVo.getUserName()) + "（就诊卡号：" + orderExtVo.getMedicalCardNo() + "），";
                            }
                            String zdfbExStr = "\n住院号：" + admissionNo + "\n收据号：" + (orderExtVo.getReceiptNum() == null ? "" : orderExtVo.getReceiptNum());

                            String msgContent = "您好，" + patientMsg + "您已成功完成一笔住院押金补缴。\n\r\n订单号：" + orderNo + "\n订单金额：" + orderExtVo.getPayAmount() / 100f + "元\n时间：" + orderExtVo.getPayTime().substring(0, 19) + zdfbExStr;
                            msgMap.put("org_code", orderExtVo.getOrgCode());
                            msgMap.put("org_app_code", orderExtVo.getPlatformOrgAppCode());
                            msgMap.put("platform_type", orderExtVo.getPayMode().toString());
                            msgMap.put("user_type", "2");
                            msgMap.put("to_user", orderExtVo.getOpenId());
                            msgMap.put("msg_content", msgContent);
                            logger.info("押金补缴支付成功后消息推送请求参数->" + JSON.toJSONString(msgMap));
                            Response messageResponse = MessageService.callHumpFromInternal("yyt.message.msg.text.send", JSON.toJSONString(msgMap));
                            logger.info("押金补缴支付成功后消息推送成功,返回->" + JSON.toJSONString(messageResponse));
                        } catch (Exception e) {
                            logger.error("押金补缴支付成功后消息推送失败:", e);
                        }

                    } else {
                        //记录写单的异常信息
                        String errMsg = payDepositVoResponse.getResultMessage();

                        //更新异常状态
                        orderExtVo.setOrderStatusException();
                        logger.info("DepositAliPayMessageListener, his_updateOrderExtVo=" + JSONObject.toJSONString(orderExtVo));
                        //保存订单信息
                        BaseService.callUnderlineFromInternal("yyt.base.order.update", JsonUtils.toJsonString(orderExtVo));
                        //异常,插入异常订单队列
                        addOrderToExceptionList(orderExtVo, errMsg);
                    }
                }
            }

        } catch (Exception e) {
            logger.error("onMessage error.", e);
        }

        logger.info("DepositAliPayMessageListener onMessage end.");
    }



    private void addOrderToExceptionList(OrderExtVo vo, String errMsg) {
        logger.info("【押金补缴支付监听-HIS写单异常,插入异常订单队列】 vo=" + JSONObject.toJSONString(vo));
        OrderExceptionVo record = new OrderExceptionVo();
        record.setBranchCode(vo.getBranchCode());
        record.setBranchId(vo.getBranchId());
        record.setBranchName(vo.getBranchName());
        record.setCreatedTime(DateUtils.dateToString(new Date()));
        record.setExceptionHandlerCount(0);
        record.setRefundHandlerCount(0);
        record.setId(PKGenerator.generateId());
        record.setIsInsurance(vo.getIsInsurance());
        record.setOrderNo(vo.getOrderNo());
        record.setOrderType(vo.getOrderType());
        record.setOrgCode(vo.getOrgCode());
        record.setOrgId(vo.getOrgId());
        record.setOrgName(vo.getOrgName());
        record.setPlatformCode(vo.getPlatformCode());
        record.setPlatformId(vo.getPlatformId());
        record.setPlatformName(vo.getPlatformName());
        record.setPlatformOrgAppCode(vo.getPlatformOrgAppCode());
        record.setUpdateTime(DateUtils.dateToString(new Date()));
        record.setHandlerResult((short) 0);
        record.setHisQueryState((short) 0);
        record.setInsuranceHandlerFlag((short) 0);
        record.setSelfPayHandlerFlag((short) 0);
        //记录写单的异常信息
        record.setExceptionReason(errMsg);
        record.setExceptionClass("Bed-DepositAliPayMessageListener");

        logger.info("【押金补缴支付监听-HIS写单异常,插入异常订单队列】 record=" + JSON.toJSONString(record));
//        CacheService.setGlobalKey(CacheConstant.CACHE_CLINIC_MODULE, CacheConstant.CACHE_CLINIC_PAY_EXCEPTION_ORDER,
//                record.getOrderNo(), JSON.toJSONString(record), CacheConstant.CACHE_NOT_EXPIRETIME);

        BaseService.callUnderlineFromInternal("", "yyt.base.order.exception.add", JsonUtils.toJsonString(record));

        logger.info("【押金补缴支付监听-HIS写单异常,插入异常订单队列】 end");
    }

    //出院结算写单
    private void paySettlement(OrderExtVo orderExtVo,String appId) {
        PayOutSettlementVo payDepositVo = new PayOutSettlementVo();
        JSONObject extraParamsMap = JsonUtils.parseObject(orderExtVo.getExtraParams());
        String patientId = (String) extraParamsMap.get("patient_id");
        String admissionNo = (String) extraParamsMap.get("admission_no");
        String inTime = (String) extraParamsMap.get("in_time");
        //拼接HIS住院押金补缴支付接口入参
        payDepositVo.setPatientId(patientId);
        payDepositVo.setAdmissionNo(admissionNo);
        payDepositVo.setInTime(inTime);
        payDepositVo.setYytOrdNum(orderExtVo.getOrderNo());
        payDepositVo.setAgtOrdNum(orderExtVo.getPaymentDealId());
        payDepositVo.setAgtCode(appId);
        payDepositVo.setPayMode(String.valueOf(orderExtVo.getPayMode()));
        payDepositVo.setPayAmount(orderExtVo.getPayAmount().toString());
        payDepositVo.setPayTime(orderExtVo.getPayTime());
        payDepositVo.setHospitalCode(orderExtVo.getOrgCode());
        logger.info("【出院结算支付监听-HIS写单】 request=" + JSONObject.toJSONString(payDepositVo));
        ResCommon<PayOutSettlementVoResponse> payDepositVoResponse = HisifaceService.getHisifaceClient().payOutSettlement(payDepositVo);
        PayDepositVoResponse payDeposit = JsonUtils.parseObject(payDepositVoResponse.getResult(),
                PayDepositVoResponse.class);
        logger.info("【出院结算支付监听-HIS写单】 response=" + JSONObject.toJSONString(payDeposit));
        if ("0".equals(payDepositVoResponse.getResultCode())) {
            orderExtVo.setHisOrderNo(payDeposit.getHisOrdNum());
            orderExtVo.setHisMessage(payDepositVoResponse.getResultMessage());
            orderExtVo.setReceiptNum(payDeposit.getReceiptNum());
            orderExtVo.setOrderStatusSuccess();
            orderExtVo.setUpdateTime(DateUtils.dateToString(new Date()));
            logger.info("DepositAliPayMessageListener, his_updateOrderExtVo=" + JSONObject.toJSONString(orderExtVo));
            //保存订单信息
            BaseService.callUnderlineFromInternal("yyt.base.order.update", JsonUtils.toJsonString(orderExtVo));

            //更新支付流水
            PaymentJournalVo tmp = new PaymentJournalVo();
            tmp.setOrderNo(orderExtVo.getOrderNo());
            tmp.setPayStatus((short) 1);
            logger.info("【出院结算支付监听-更新支付流水】addPaymentJournal, paymentJournal=" + JSON.toJSONString(tmp));
            Response findPaymentJournalResponse = PayService.callUnderlineFromInternal("yyt.pay.payment.journal.find",
                    JsonUtils.toJsonString(tmp));
            logger.info("【出院结算支付监听-更新支付流水】addPaymentJournal, findPaymentJournalResponse=" + JSON.toJSONString(findPaymentJournalResponse));
            if ("0".equals(findPaymentJournalResponse.getResultCode())) {
                List<PaymentJournalVo> pjs = JsonUtils.parseArray(findPaymentJournalResponse.getResult(),
                        PaymentJournalVo.class);
                PaymentJournalVo psv = pjs.get(0);
                psv.setHisOrderNo(payDeposit.getHisOrdNum());
                logger.info("【出院结算支付监听-更新支付流水】修改支付流水请求参数->" + JSON.toJSONString(psv));
                PayService.callUnderlineFromInternal("yyt.pay.payment.journal.update", JsonUtils.toJsonString(psv));
            }

            //文本消息推送
            try {
                Map<String, String> msgMap = new HashMap<String, String>();
                String patientMsg = "";
                if (StringUtils.isNotBlank(orderExtVo.getMedicalCardNo())) {
                    patientMsg = MedicalCardUtil.desName(orderExtVo.getUserName()) + "（就诊卡号：" + orderExtVo.getMedicalCardNo() + "），";
                }
                String zdfbExStr = "\n温馨提示：如需打印发票、费用清单、办理退款等业务，请到窗口办理。";
                String msgContent = "您好，" + patientMsg + "您已成功完成出院结算。\n\r\n订单号：" + orderExtVo.getOrderNo() + "\n订单金额：" + orderExtVo.getPayAmount() / 100f + "元\n时间：" + orderExtVo.getPayTime().substring(0, 19) + zdfbExStr;

                msgMap.put("org_code", orderExtVo.getOrgCode());
                msgMap.put("org_app_code", orderExtVo.getPlatformOrgAppCode());
                msgMap.put("platform_type", orderExtVo.getPayMode().toString());
                msgMap.put("user_type", "2");
                msgMap.put("to_user", orderExtVo.getOpenId());
                msgMap.put("msg_content", msgContent);
                logger.info("出院结算支付成功后消息推送请求参数->" + JSON.toJSONString(msgMap));
                Response messageResponse = MessageService.callHumpFromInternal("yyt.message.msg.text.send", JSON.toJSONString(msgMap));
                logger.info("出院结算支付成功后消息推送成功,返回->" + JSON.toJSONString(messageResponse));
            } catch (Exception e) {
                logger.error("出院结算支付成功后消息推送失败:", e);
            }

        } else {
            //记录写单的异常信息
            String errMsg = payDepositVoResponse.getResultMessage();

            //更新异常状态
            orderExtVo.setOrderStatusException();
            logger.info("DepositAliPayMessageListener, his_updateOrderExtVo=" + JSONObject.toJSONString(orderExtVo));
            //保存订单信息
            BaseService.callUnderlineFromInternal("yyt.base.order.update", JsonUtils.toJsonString(orderExtVo));
            //异常,插入异常订单队列
            addOrderToExceptionList(orderExtVo, errMsg);
        }
    }
}